<template>
  <div
    v-if="tocData.length > 0"
    class="article-toc"
    :class="{ expanded: isExpanded }"
  >
    <!-- 顶部标题栏 -->
    <div class="toc-header">
      <h4 class="toc-title">
        目录
        <span v-if="!isExpanded" class="toc-count-badge"
          >({{ displayTocData.length + (categoryTitle ? 1 : 0) }})</span
        >
      </h4>
      <button class="toc-toggle-btn" @click="toggleToc">
        {{ isExpanded ? "收起" : "展开" }}
      </button>
    </div>

    <!-- 内容区域 -->
    <div
      v-show="isExpanded"
      class="toc-content"
      :class="{ scrollable: isContentScrollable }"
      :style="tocContentStyle"
    >
      <div class="toc-list">
        <!-- 分类标题（第一个H1） -->
        <div v-if="categoryTitle" class="toc-category">
          {{ categoryTitle }}
        </div>

        <!-- 目录项列表 -->
        <div
          v-for="item in displayTocData"
          :key="item.id"
          :class="[
            'toc-item',
            `toc-level-${item.level}`,
            { 'toc-item--active': activeId === item.id }
          ]"
          @click="scrollToHeading(item.id)"
        >
          {{ item.text }}
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  ref,
  computed,
  onMounted,
  onBeforeUnmount,
  watch,
  nextTick
} from "vue";

interface TocItem {
  id: string;
  text: string;
  level: number;
  element?: HTMLElement;
}

interface Props {
  /** 文章内容HTML */
  content?: string;
  /** 是否自动生成目录 */
  autoGenerate?: boolean;
  /** 目录最大层级 */
  maxLevel?: number;
}

const props = withDefaults(defineProps<Props>(), {
  autoGenerate: true,
  maxLevel: 4
});

// 响应式数据
const tocData = ref<TocItem[]>([]);
const activeId = ref<string>("");
const isExpanded = ref(false); // 移动端默认收起
const isContentScrollable = ref(false); // 内容是否可滚动

// 计算属性：分类标题（第一个H1标题）
const categoryTitle = computed(() => {
  const firstH1 = tocData.value.find(item => item.level === 1);
  return firstH1?.text || null;
});

// 计算属性：显示的目录数据（除去第一个H1）
const displayTocData = computed(() => {
  if (categoryTitle.value) {
    return tocData.value.slice(1); // 除去第一个作为分类标题
  }
  return tocData.value;
});

// 计算属性：根据条目数量动态计算合适的高度
const tocContentStyle = computed(() => {
  const displayItemCount = displayTocData.value.length;
  const hasCategoryTitle = !!categoryTitle.value;

  if (displayItemCount === 0) {
    return {
      maxHeight: "60px",
      overflow: "hidden"
    };
  }

  // 动态计算可用空间（考虑侧边栏高度）
  const sidebarHeight = window.innerHeight - 40; // 侧边栏可用高度
  const headerHeight = 60; // 目录头部高度
  const relatedArticlesEstimatedHeight = 200; // 相关推荐估计高度
  const padding = 40; // 内边距和间隙

  // 目录内容区最大可用高度
  const availableHeight =
    sidebarHeight - headerHeight - relatedArticlesEstimatedHeight - padding;

  // 设置合理的最大高度范围
  const maxContentHeight = Math.max(150, Math.min(500, availableHeight));

  console.log(
    `目录条目数: ${displayItemCount}, 可用高度: ${availableHeight}px, 最大高度: ${maxContentHeight}px`
  );

  // 始终使用 maxHeight 和滚动，让内容自适应
  return {
    maxHeight: `${maxContentHeight}px`,
    overflowY: "auto",
    overflowX: "hidden",
    height: "auto"
  };
});

/**
 * 解析HTML内容生成目录
 */
const parseContent = (htmlContent: string): TocItem[] => {
  if (!htmlContent) return [];

  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlContent, "text/html");
  const headings = doc.querySelectorAll("h1, h2, h3, h4, h5, h6");

  const items: TocItem[] = [];

  headings.forEach((heading, index) => {
    const level = parseInt(heading.tagName.substring(1));
    if (level > props.maxLevel) return;

    const text = heading.textContent?.trim() || "";
    if (!text) return;

    // 生成ID（如果没有的话）
    let id = heading.getAttribute("id");
    if (!id) {
      id = `heading-${index}-${text.replace(/\s+/g, "-").toLowerCase()}`;
      heading.setAttribute("id", id);
    }

    items.push({
      id,
      text,
      level
    });
  });

  return items;
};

/**
 * 从当前页面的DOM元素生成目录
 */
const generateTocFromDOM = (): TocItem[] => {
  const headings = document.querySelectorAll(
    ".article-content h1, .article-content h2, .article-content h3, .article-content h4, .article-content h5, .article-content h6"
  );
  const items: TocItem[] = [];

  headings.forEach((heading, index) => {
    const level = parseInt(heading.tagName.substring(1));
    if (level > props.maxLevel) return;

    const text = heading.textContent?.trim() || "";
    if (!text) return;

    // 生成ID（如果没有的话）
    let id = heading.getAttribute("id");
    if (!id) {
      id = `heading-${index}-${text.replace(/\s+/g, "-").toLowerCase()}`;
      heading.setAttribute("id", id);
    }

    items.push({
      id,
      text,
      level,
      element: heading as HTMLElement
    });
  });

  return items;
};

/**
 * 滚动到指定标题
 */
const scrollToHeading = (id: string) => {
  const element = document.getElementById(id);
  if (element) {
    // 计算偏移量（考虑固定头部等）
    const offset = 80; // 头部高度 + 一些边距
    const elementPosition = element.offsetTop - offset;

    window.scrollTo({
      top: elementPosition,
      behavior: "smooth"
    });

    // 更新活跃状态
    activeId.value = id;
  }
};

/**
 * 自动滚动目录到当前活跃项
 */
const scrollTocToActive = (activeItemId: string) => {
  if (!activeItemId) return;

  // 等待DOM更新
  setTimeout(() => {
    const tocContent = document.querySelector(".toc-content");
    const activeItem = document.querySelector(
      `.toc-item a[href="#${activeItemId}"]`
    );

    if (tocContent && activeItem) {
      const tocContentRect = tocContent.getBoundingClientRect();
      const activeItemRect = activeItem.getBoundingClientRect();

      // 计算活跃项目在目录容器中的位置
      const activeItemTop =
        activeItemRect.top - tocContentRect.top + tocContent.scrollTop;
      const tocHeight = tocContent.clientHeight;
      const itemHeight = 36; // 项目高度

      // 如果活跃项目不在可视区域内，则滚动目录
      if (
        activeItemTop < tocContent.scrollTop ||
        activeItemTop > tocContent.scrollTop + tocHeight - itemHeight * 2
      ) {
        // 滚动到项目中心位置
        const scrollTop = Math.max(
          0,
          activeItemTop - tocHeight / 2 + itemHeight / 2
        );

        tocContent.scrollTo({
          top: scrollTop,
          behavior: "smooth"
        });
      }
    }
  }, 100);
};

/**
 * 监听滚动更新活跃项
 */
const handleScroll = () => {
  const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
  const offset = 100; // 偏移量

  // 找到当前视口中的标题
  let currentId = "";

  for (let i = tocData.value.length - 1; i >= 0; i--) {
    const item = tocData.value[i];
    const element = document.getElementById(item.id);
    if (element) {
      const elementTop = element.offsetTop - offset;
      if (scrollTop >= elementTop) {
        currentId = item.id;
        break;
      }
    }
  }

  activeId.value = currentId;
};

/**
 * 切换目录展开/收起状态
 */
const toggleToc = () => {
  isExpanded.value = !isExpanded.value;
  // 展开时检测是否需要滚动
  if (isExpanded.value) {
    nextTick(() => {
      checkScrollable();
    });
  }
};

/**
 * 检测目录内容是否可滚动
 */
const checkScrollable = () => {
  const tocContent = document.querySelector(".toc-content");
  if (tocContent) {
    const hasVerticalScrollbar =
      tocContent.scrollHeight > tocContent.clientHeight;
    isContentScrollable.value = hasVerticalScrollbar;
    console.log(`目录内容可滚动: ${hasVerticalScrollbar}`);
  }
};

/**
 * 初始化目录
 */
const initToc = () => {
  if (props.autoGenerate) {
    // 等待DOM更新后再生成目录
    setTimeout(() => {
      tocData.value = generateTocFromDOM();
      console.log("目录生成完成:", tocData.value.length, "个条目");
      debugTocData(); // 在目录生成后调试

      // 桌面端默认展开，移动端默认收起
      const isMobile = window.innerWidth <= 767;
      isExpanded.value = !isMobile;
    }, 100);
  } else if (props.content) {
    tocData.value = parseContent(props.content);
    console.log("从内容解析目录:", tocData.value.length, "个条目");
    debugTocData();

    // 桌面端默认展开，移动端默认收起
    const isMobile = window.innerWidth <= 767;
    isExpanded.value = !isMobile;
  }
};

// 监听内容变化
watch(
  () => props.content,
  () => {
    initToc();
    // 目录更新后检测滚动状态
    nextTick(() => {
      if (isExpanded.value) {
        checkScrollable();
      }
    });
  },
  { immediate: true }
);

// 监听目录数据变化
watch(
  () => tocData.value.length,
  () => {
    nextTick(() => {
      if (isExpanded.value) {
        checkScrollable();
      }
    });
  }
);

// 监听活跃ID变化，自动滚动目录
watch(activeId, newActiveId => {
  if (newActiveId) {
    scrollTocToActive(newActiveId);
  }
});

/**
 * 监听来自 ArticleBody 的目录锚点高亮事件
 */
const handleArticleHeadingChange = (event: CustomEvent) => {
  const { activeId } = event.detail;
  console.log("📌 目录组件接收到标题激活事件:", activeId);
  activeId.value = activeId;
};

// 生命周期
onMounted(() => {
  initToc();

  // 添加滚动监听
  window.addEventListener("scroll", handleScroll, { passive: true });

  // 监听窗口大小变化，重新计算高度
  window.addEventListener("resize", handleWindowResize);

  // 监听来自 ArticleBody 的目录锚点高亮事件
  document.addEventListener(
    "article-heading-change",
    handleArticleHeadingChange
  );

  // 初始检查活跃项和滚动状态
  setTimeout(() => {
    handleScroll();
    if (isExpanded.value) {
      checkScrollable();
    }
    console.log("延迟检查目录状态...");
    debugTocData(); // 调试目录数据
  }, 500);
});

onBeforeUnmount(() => {
  window.removeEventListener("scroll", handleScroll);
  window.removeEventListener("resize", handleWindowResize);
  document.removeEventListener(
    "article-heading-change",
    handleArticleHeadingChange
  );
});

// 处理窗口大小变化（包括缩放）
const handleWindowResize = () => {
  // 重新计算目录高度并检测滚动状态
  console.log("窗口尺寸变化，重新计算目录高度");
  nextTick(() => {
    tocContentStyle.value; // 触发重新计算
    if (isExpanded.value) {
      checkScrollable(); // 检测滚动状态
    }
  });
};

// 调试函数
const debugTocData = () => {
  console.log("目录数据:", tocData.value);
  console.log("目录样式:", tocContentStyle.value);
};

// 暴露方法
defineExpose({
  refreshToc: initToc,
  scrollToHeading,
  debugTocData
});
</script>

<style lang="scss" scoped>
// 现代极简主义目录组件
.article-toc {
  display: flex;
  flex-direction: column;
  font-family:
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, sans-serif;
  background: #fff;
  border: 1px solid #f0f0f0;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgb(0 0 0 / 6%);
  transition: box-shadow 0.2s ease;

  // 移动端适配
  @media screen and (width <= 999px) {
    position: static !important;
    top: auto !important;
    border-radius: 6px;
    box-shadow: 0 1px 4px rgb(0 0 0 / 8%);

    .toc-header {
      padding: 12px 16px;
      border-radius: 6px 6px 0 0;

      .toc-title {
        font-size: 16px;
      }

      .toc-toggle-btn {
        font-size: 13px;
      }
    }

    .toc-content {
      max-height: 50vh !important; // 移动端限制最大高度为视口的50%
      border-radius: 0 0 6px 6px;

      &::-webkit-scrollbar {
        width: 3px;
      }

      &.scrollable {
        &::before,
        &::after {
          right: 3px !important;
        }
      }
    }

    .toc-list {
      padding: 12px 0;

      .toc-category {
        padding: 0 16px 10px;
        font-size: 15px;
      }

      .toc-item {
        padding: 6px 12px;
        margin: 0 12px 3px;
        font-size: 13px;

        &.toc-level-1 {
          padding-left: 16px;
        }

        &.toc-level-2 {
          padding-left: 24px;
        }

        &.toc-level-3 {
          padding-left: 32px;
          font-size: 12px;
        }

        // 移动端隐藏深层级
        &.toc-level-4,
        &.toc-level-5,
        &.toc-level-6 {
          display: none;
        }
      }
    }
  }

  // 暗色模式适配
  @media (prefers-color-scheme: dark) {
    background: #1a1a1a;
    border-color: #333;
    box-shadow: 0 2px 8px rgb(0 0 0 / 20%);

    &:hover {
      box-shadow: 0 4px 12px rgb(0 0 0 / 30%);
    }

    .toc-header {
      background: #1a1a1a;
      border-color: #333;

      .toc-title {
        color: #fff;

        .toc-count-badge {
          color: #bbb;
          background: #333;
        }
      }

      .toc-toggle-btn {
        color: #bbb;

        &:hover {
          color: #fff;
          background: #333;
        }
      }
    }

    .toc-content {
      background: #1a1a1a;

      &::-webkit-scrollbar-track {
        background: rgb(255 255 255 / 5%);
      }

      &::-webkit-scrollbar-thumb {
        background: rgb(255 255 255 / 20%);

        &:hover {
          background: rgb(255 255 255 / 30%);
        }

        &:active {
          background: rgb(79 195 247 / 40%);
        }
      }

      &.scrollable {
        &::before {
          background: linear-gradient(to bottom, #1a1a1a, transparent);
        }

        &::after {
          background: linear-gradient(to top, #1a1a1a, transparent);
        }
      }
    }

    .toc-list {
      .toc-category {
        color: #4fc3f7;
      }

      .toc-item {
        color: #ccc;

        &:hover {
          color: #fff;
          background: #2a2a2a;
        }

        &.toc-item--active {
          color: #4fc3f7;
          background: #1e3a5f;
          border-left-color: #4fc3f7;
        }
      }
    }
  }

  &:hover {
    box-shadow: 0 4px 12px rgb(0 0 0 / 8%);
  }

  // 顶部标题栏
  .toc-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    background: #fff;
    border-bottom: 1px solid #f0f0f0;
    border-radius: 8px 8px 0 0;

    .toc-title {
      display: flex;
      gap: 8px;
      align-items: center;
      margin: 0;
      font-size: 18px;
      font-weight: 600;
      color: #333;
      text-align: left;

      .toc-count-badge {
        padding: 2px 6px;
        font-size: 12px;
        font-weight: 400;
        color: #999;
        background: #f5f5f5;
        border-radius: 10px;
        transition: all 0.2s ease;
      }
    }

    .toc-toggle-btn {
      padding: 4px 8px;
      font-family: inherit;
      font-size: 14px;
      color: #999;
      cursor: pointer;
      background: none;
      border: none;
      border-radius: 4px;
      transition: all 0.2s ease;

      &:hover {
        color: #666;
        background: #f5f5f5;
      }

      &:active {
        transform: translateY(1px);
      }
    }
  }

  // 内容区域
  .toc-content {
    position: relative;
    background: #fff;
    border-radius: 0 0 8px 8px;

    // 自定义滚动条
    &::-webkit-scrollbar {
      width: 6px;
    }

    &::-webkit-scrollbar-track {
      margin: 4px 0;
      background: rgb(0 0 0 / 2%);
      border-radius: 3px;
    }

    &::-webkit-scrollbar-thumb {
      background: rgb(0 0 0 / 10%);
      border-radius: 3px;
      transition: background 0.2s ease;

      &:hover {
        background: rgb(0 0 0 / 20%);
      }

      &:active {
        background: rgb(25 118 210 / 30%);
      }
    }

    // 滚动时显示渐变遮罩效果
    &.scrollable {
      &::before {
        position: absolute;
        top: 0;
        right: 6px;
        left: 0;
        z-index: 1;
        height: 8px;
        pointer-events: none;
        content: "";
        background: linear-gradient(to bottom, #fff, transparent);
      }

      &::after {
        position: absolute;
        right: 6px;
        bottom: 0;
        left: 0;
        z-index: 1;
        height: 8px;
        pointer-events: none;
        content: "";
        background: linear-gradient(to top, #fff, transparent);
      }
    }
  }

  // 目录列表
  .toc-list {
    padding: 16px 0;
    margin: 0;
    list-style: none;

    // 分类标题
    .toc-category {
      padding: 0 20px 12px;
      margin-bottom: 8px;
      font-size: 16px;
      font-weight: 600;
      color: #1976d2;
      text-align: left;
      text-decoration: underline;
    }

    // 目录项
    .toc-item {
      padding: 8px 20px;
      margin: 0 16px 4px;

      // 基础样式
      font-size: 14px;
      line-height: 1.5;
      color: #666;
      text-align: left;
      cursor: pointer;
      border-radius: 4px;
      transition: all 0.2s ease;

      &:last-child {
        margin-bottom: 0;
      }

      // 悬停效果
      &:hover {
        color: #333;
        background: #f8f9fa;
      }

      // 选中状态
      &.toc-item--active {
        padding-left: 17px;
        color: #1976d2;
        background: #e3f2fd;
        border-left: 3px solid #1976d2;
      }

      // 层级缩进
      &.toc-level-1 {
        padding-left: 20px;
        font-weight: 500;
      }

      &.toc-level-2 {
        padding-left: 32px;
      }

      &.toc-level-3 {
        padding-left: 44px;
        font-size: 13px;
      }

      &.toc-level-4 {
        padding-left: 56px;
        font-size: 13px;
      }

      &.toc-level-5,
      &.toc-level-6 {
        padding-left: 68px;
        font-size: 12px;
      }
    }
  }

  // 收起状态下的样式优化
  &:not(.expanded) {
    .toc-header {
      cursor: pointer;
      border-radius: 8px; // 全圆角
      transition: all 0.3s ease;

      &:hover {
        border-color: rgb(25 118 210 / 30%);
        box-shadow: 0 6px 20px rgb(0 0 0 / 15%);
        transform: translateY(-2px);

        .toc-title {
          color: #1976d2;

          .toc-count-badge {
            color: #1976d2;
            background: rgb(25 118 210 / 10%);
          }
        }

        .toc-toggle-btn {
          color: #1976d2;
          background: rgb(25 118 210 / 10%);
        }
      }

      .toc-toggle-btn {
        &::after {
          font-size: 12px;
          content: " 点击展开";
          opacity: 0;
          transition: opacity 0.2s ease;
        }
      }

      &:hover .toc-toggle-btn::after {
        opacity: 1;
      }
    }
  }
}
</style>
